package com.cms.kernel.shiro;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.cms.admin.service.AdminService;
import com.cms.kernel.entity.Admin;
import com.cms.kernel.exception.JEEWellException;
import com.cms.kernel.util.RequestUtil;
import com.cms.kernel.util.ResponseUtil;
import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.image.ImageCaptchaService;

/**
 * Copyright (C) 2013 2016 Well
 * 文件:AdminLoginAuthenticationFilter.java
 * 创建:Well
 * 日期:2016年6月23日 下午2:50:15
 * 来自:
 * 版本:
 * 描述:后台管理员登录认证的过滤类
 */

public class AdminLoginAuthenticationFilter extends FormAuthenticationFilter
{
	private static Logger logger=LogManager.getLogger(FormAuthenticationFilter.class);
	
	@Autowired
	private AdminService adminService;
	
	@Autowired
	private ImageCaptchaService imageCaptchaService;
	
	/**
	 * 
	 */
	@Override
	protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
	{
//		logger.info("isAccessAllowed");
		
		Subject subject=super.getSubject(request, response);
		if(null!=subject)
		{
			if(subject.isAuthenticated()) // 已经认证
			{
				// TODO:如果已经认证，需要做什么
			}
			else // 没有认证
			{
				if(subject.isRemembered()) // 如果上一次登录时，选择记住我（自动登录）
				{
					Admin admin=(Admin) subject.getPrincipal();
					if(null!=admin)
					{
						adminService.autoLogin(admin);
						return true;
					}
				}
				/* 当进行AJAX请求时，由于用户登录状态已经失效，需要在AJAX响应头中存储session失效的标记 */
				if(RequestUtil.isAJAXRequest(WebUtils.toHttp(request))) // 如果是AJAX请求
				{
					if(!super.isLoginRequest(request,response)) // 不是登录请求
					{
						/* 用户登录失效，在响应头中存储session失效的标记 */
	                    WebUtils.toHttp(response).setHeader("session-status","session-invalid");
	                    return true;
					}
				}
			}
		}
		
		return super.isAccessAllowed(request, response, mappedValue);
	}
	
	/**
	 * 
	 */
	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
	{
//		logger.info("onAccessDenied");
		
		/* 是登录请求 并且是 AJAX登录请求 */
		if(super.isLoginRequest(request, response) && super.isLoginSubmission(request, response))
		{
			return this.executeLogin(request, response);
		}
		return super.onAccessDenied(request, response);
	}
	
	/**
	 * 执行登录
	 */
	@Override
	protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception
	{
//		logger.info("executeLogin");
		
		boolean result=false;
		
		try
		{
			String id=RequestUtil.getSessionID(WebUtils.toHttp(request));
			String captcha=request.getParameter("captcha"); // 验证码
			
			/* 验证码校验 */
			if(imageCaptchaService.validateResponseForID(id, captcha).booleanValue()) // 如果验证码正确
			{
				String username=request.getParameter("username"); // 管理员的登录名称
				String password=request.getParameter("password"); // 管理员登录密码
				boolean rememberMe=StringUtils.equals("on",request.getParameter("rememberMe")); // 是否记住我（自动登录）
				
				UsernamePasswordToken token=new UsernamePasswordToken(username,password,rememberMe);
	            Subject subject=getSubject(request,response);
	            subject.login(token);
	            
	            Session session=subject.getSession(true);
	            logger.info("【"+username+"】登录成功，有效时间为【"+session.getTimeout()+"】毫秒！");
	            result=true;
			}
			else // 如果验证码不正确
			{
				logger.error("验证码错误！");
				result=false;
			}
		}
		catch(CaptchaServiceException e) // 验证码失效异常
		{
			logger.error(e);
			result=false;
//			throw new JEEWellException("验证码失效！");
		}
		catch(UnknownAccountException e) // 用户名称不存在异常
		{
			logger.error(e);
			result=false;
		}
		catch(IncorrectCredentialsException e) // 密码错误异常
		{
			logger.error(e);
			result=false;
		}
		catch(LockedAccountException e) // 用户被锁定异常
		{
			logger.error(e);
			result=false;
		}
		catch(AuthenticationException e) // 用户认证异常
		{
			logger.error(e);
			result=false;
		}
		finally
		{
			ResponseUtil.renderJSON(WebUtils.toHttp(response), "{success:\""+String.valueOf(result)+"\"}");
		}
		
		return false;
	}
}
